package com.binioter.guideview;

import ohos.aafwk.ability.AbilitySlice;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.app.Context;
import ohos.multimodalinput.event.KeyEvent;
import ohos.multimodalinput.event.TouchEvent;

/**
 * 遮罩系统的封装 <br>
 * 外部需要调用{@link GuideBuilder}来创建该实例，实例创建后调用
 * {@link #show(AbilitySlice activity, ComponentContainer rootView, int media_arrow, String Text)}
 * 控制显示； 调用 {@link #dismiss()}让遮罩系统消失。 <br>
 * <p>
 * Created by binIoter
 */
/**
 * 遮罩系统运行异常的封装
 *
 * Created by binIoter
 *
 * @since 2021-04-19
 *
 */
public class Guide implements Component.TouchEventListener, ComponentContainer.KeyEventListener {
    /**
     * 滑动临界值
     */
    private static final int SLIDE_THRESHOLD = 30;
    private Configuration mConfiguration;
    private MaskView mMaskView;
    private viewComment[] mViewComments;
    private float startY = -1f;


    // 根据locInwindow定位后，是否需要判断loc值非0
    private GuideBuilder.OnVisibilityChangedListener mOnVisibilityChangedListener;
    private GuideBuilder.OnSlideListener mOnSlideListener;

    void setConfiguration(Configuration configuration) {
        mConfiguration = configuration;
    }

    void setComponents(viewComment[] viewComments) {
        mViewComments = viewComments;
    }

    void setCallback(GuideBuilder.OnVisibilityChangedListener listener) {
        this.mOnVisibilityChangedListener = listener;
    }

    public void setOnSlideListener(GuideBuilder.OnSlideListener onSlideListener) {
        this.mOnSlideListener = onSlideListener;
    }

    /**
     * 显示遮罩
     *
     * @param activity 目标Activity
     * @param rootView 根布局
     * @param mediaArrow 指针
     * @param text 指针文字
     */
    public void show(AbilitySlice activity, ComponentContainer rootView, int mediaArrow, String text) {
        showZ(activity, rootView, mediaArrow, text);
    }

    /**
     * 显示遮罩
     *
     * @param activity 目标Activity
     * @param overlay 遮罩层view
     * @param id 指针id
     * @param text 文字id
     */
    public void showZ(AbilitySlice activity, ComponentContainer overlay, int id, String text) {
        mMaskView = onCreateView(activity, overlay);
        mMaskView.setText(text);
        mMaskView.setImaId(id);
        if (mMaskView.getComponentParent() == null && mConfiguration.mTargetView != null) {
            overlay.addComponent(mMaskView);
            if (mConfiguration.mEnterAnimationId != -1) {
                AnimatorProperty animatorProperty = new AnimatorProperty(overlay);
                animatorProperty.setStateChangedListener(new Animator.StateChangedListener() {
                    @Override
                    public void onStart(Animator animator) {
                        if (mOnVisibilityChangedListener != null) {
                            mOnVisibilityChangedListener.onShown();
                        }
                    }

                    @Override
                    public void onStop(Animator animator) {
                    }

                    @Override
                    public void onCancel(Animator animator) {
                    }

                    @Override
                    public void onEnd(Animator animator) {
                    }

                    @Override
                    public void onPause(Animator animator) {
                    }

                    @Override
                    public void onResume(Animator animator) {
                    }
                });
            } else {
                if (mOnVisibilityChangedListener != null) {
                    mOnVisibilityChangedListener.onShown();
                }
            }
        }
    }

    public void clear() {
        if (mMaskView == null) {
            return;
        }
        final ComponentContainer vp = (ComponentContainer) mMaskView.getComponentParent();
        if (vp == null) {
            return;
        }
        vp.removeComponent(mMaskView);
        onDestroy();
    }

    /**
     * 隐藏该遮罩并回收资源相关
     */
    public void dismiss() {
        if (mMaskView == null) {
            return;
        }
        final ComponentContainer vp = (ComponentContainer) mMaskView.getComponentParent();
        if (vp == null) {
            return;
        }
        if (mConfiguration.mExitAnimationId != -1) {
            // mMaskView may leak if context is null
            Context context = mMaskView.getContext();
            assert context != null;
        } else {
            if (mOnVisibilityChangedListener != null) {
                mOnVisibilityChangedListener.onDismiss();
            }
            vp.removeComponent(mMaskView);
            onDestroy();
        }
    }

    private MaskView onCreateView(AbilitySlice activity, ComponentContainer overlay) {
        MaskView maskView = new MaskView(activity);
        maskView.setFullingColor(mConfiguration.mFullingColorId);
        maskView.setFullingAlpha(mConfiguration.mAlpha);
        maskView.setHighTargetCorner(mConfiguration.mCorner);
        maskView.setPadding(mConfiguration.mPadding);
        maskView.setPaddingLeft(mConfiguration.mPaddingLeft);
        maskView.setPaddingTop(mConfiguration.mPaddingTop);

        maskView.setPaddingRight(mConfiguration.mPaddingRight);
        maskView.setPaddingBottom(mConfiguration.mPaddingBottom);
        maskView.setHighTargetGraphStyle(mConfiguration.mGraphStyle);
        maskView.setOverlayTarget(mConfiguration.mOverlayTarget);
        maskView.setKeyEventListener(this::onKeyEvent);
        maskView.getLocationOnScreen();
        int parentX = 0;
        int parentY = 0;

        if (overlay != null) {
            int[] loc = overlay.getLocationOnScreen();
            parentX = loc[0];
            parentY = loc[1];
        }
        if (mConfiguration.mTargetView != null) {
            int[] locationOnScreen = mConfiguration.mTargetView.getLocationOnScreen();
            maskView.setTargetRect(Common.getViewAbsRect(mConfiguration.mTargetView, locationOnScreen[0], locationOnScreen[1]));
        } else {
            // Gets the target view's abs rect
            Component target = activity.findComponentById(mConfiguration.mTargetViewId);
            if (target != null) {
                maskView.setTargetRect(Common.getViewAbsRect(target, parentX, parentY));
            }
        }

        if (mConfiguration.mOutsideTouchable) {
            overlay.setEnabled(false);
            maskView.setTouchEventListener(this::onTouchEvent);
        } else {
            maskView.setTouchEventListener(this::onTouchEvent);
        }

//        maskView.setComponents(mViewComments);
        return maskView;
    }

    private void onDestroy() {
        mConfiguration = null;
        mViewComments = null;
        mOnVisibilityChangedListener = null;
        mOnSlideListener = null;
        mMaskView.removeAllComponents();
        mMaskView = null;
    }

    @Override
    public boolean onKeyEvent(Component component, KeyEvent keyEvent) {
        if (keyEvent.getKeyCode() == KeyEvent.KEY_BACK && keyEvent.getKeyCode() == KeyEvent.KEY_DPAD_UP) {
            if (mConfiguration != null && mConfiguration.mAutoDismiss) {
                dismiss();
                return true;
            } else {
                return false;
            }
        }

        return false;
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent motionEvent) {
        if (motionEvent.getAction() == TouchEvent.PRIMARY_POINT_DOWN) {
            startY = component.getPivotY();
            return true;
        } else if (motionEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
            if ((double)startY - (double)component.getPivotY() > (double)DensityUtils.fpToPx(component.getContext(), Float.valueOf(SLIDE_THRESHOLD))) {
                if (mOnSlideListener != null) {
                    mOnSlideListener.onSlideListener(GuideBuilder.SlideState.UP);
                }
            } else if ((double)component.getPivotY() - (double)startY > (double)DensityUtils.fpToPx(component.getContext(), Float.valueOf(SLIDE_THRESHOLD))) {
                if (mOnSlideListener != null) {
                    mOnSlideListener.onSlideListener(GuideBuilder.SlideState.DOWN);
                }
            }
            if (mConfiguration != null && mConfiguration.mAutoDismiss) {
                dismiss();
            }
        }
        return false;
    }
}
